﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GcmpGraphicsNodeInterface.h"
#include "IDbObject.h"

#include "GbmpCommon.h"
#include "GraphicsNodeId.h"
#include "Box3d.h"
#include "GraphicsNodeType.h"
#include "GraphicsNodeVisibility.h"
#include "GraphicsRenderLayer.h"

namespace Json
{
    class Value;
};

namespace gcmp
{
    class Matrix4d;
    class IGraphicsNodeVisibilityFilter;
    class GcmpJsonWrapper;

    /// \brief 图形节点
    class GCMP_GRAPHICS_NODE_INTERFACE_EXPORT IGraphicsNode : public IDbObject
    {
        DEFINE_CAST_DERIVED(IGraphicsNode, IDbObject)

    public:
        /// \brief 析构器
        virtual ~IGraphicsNode();

    public:
        /// \brief 将图形节点转化为Json对象
        ///
        /// Json格式示例:
        /// {
        /// "graphicsNodeType": 14, //Int32类型，图形节点的类型。比如是Face，Body，Text
        /// "graphicsNodeId" : 1,   //Int32类型
        /// "gStyleId" : 2,         //Int64类型，GStyleElement的ElementId
        /// "geometry" : "xxxxxx",  //GGP二进制几何数据
        /// "subNodes" : [{}, {}]    //数组类型。其中每一个对象也是该Json对象
        /// "vis" :                 //Int32类型，图形节点的可见性，见GraphicsNodeVisibility。
        /// }
        /// \param pElement 图形节点所在的Element对象
        /// \return Json对象
        virtual Json::Value ToJson(const IElement* pElement) const = 0;

        /// \brief 根据Json对象创建图形节点
        ///
        /// Json格式示例:
        /// {
        /// "graphicsNodeType": 14, //Int32类型，图形节点的类型。比如是Face，Body，Text
        /// "graphicsNodeId" : 1,   //Int32类型
        /// "gStyleId" : 2,         //Int64类型，GStyleElement的ElementId
        /// "geometry" : "xxxxxx",  //GGP二进制几何数据
        /// "subNodes" : [{}, {}]    //数组类型。其中每一个对象也是该Json对象
        /// "vis" :                 //Int32类型，图形节点的可见性，见GraphicsNodeVisibility。
        /// }
        /// \param jsonObject Json对象
        /// \return OwnerPtr<IGraphicsNode> 创建的图形节点
        static OwnerPtr<IGraphicsNode> CreateFromJson(const GcmpJsonWrapper &pJsonWrapper);
        static OwnerPtr<IGraphicsNode> CreateFromJson(const std::string &strJson);

        /// \brief 获取节点的三维包围盒
        /// \return 三维包围盒
        virtual Box3d GetBox() const = 0;

        /// \brief 获取节点的标识符id
        /// \return 节点的标识符id
        virtual GraphicsNodeId GetId() const = 0;

        /// \brief 设置节点的标识符id
        /// \param id 节点的标识符id
        /// \return true-设置成功；false-设置失败
        virtual bool SetId(const GraphicsNodeId& id) = 0;

        /// \brief 获取节点的可见性
        /// \return true-节点可见；false-节点不可见
        virtual bool IsVisible() const = 0;

        /// \brief 获取节点类型
        /// \return 表示节点类型的枚举值
        virtual GraphicsNodeType GetType() const = 0;
        
        /// \brief 获取节点上的标签
        /// \return 节点上的标签
        virtual Guid GetTag() const = 0;

        ///// \brief 给节点设置标签
        ///// \param tag 设置在节点上的标签
        //virtual void SetTag(const Guid& tag) = 0;

        /// \brief 获取节点的图形样式id
        /// \return 节点的图形样式id
        virtual ElementId GetGraphicsStyleId() const = 0;

        /// \brief 设置节点的图形样式id
        /// \param id 图形样式id
        /// \return true-设置成功；false-设置失败
        virtual bool SetGraphicsStyleId(const ElementId& id) = 0;

        /// \brief 获取节点的图形显示材质id
        /// \return 节点的图形显示材质id
        virtual ElementId GetGraphicsMaterialId() const = 0;

        /// \brief 设置节点的图形显示材质id
        /// \param id 图形显示材质id
        /// \return 无
        virtual void SetGraphicsMaterialId(const ElementId& id) = 0;
        
        /// \brief 重载节点上的漫反射纹理变换
        /// \param offset 漫反射纹理的偏移量
        /// \param rotation 漫反射纹理的旋转量（单位：角度）
        /// \param scale 漫反射纹理的缩放量
        virtual void OverrideDiffuseTexureTransformation(const Vector2d& offset, double rotation, const Vector2d& scale) = 0;

        /// \brief 删除节点上重载的漫反射纹理变换
        virtual void DeleteOverriddenDiffuseTexureTransformation() = 0;

        /// \brief 获取节点上重载的漫反射纹理变换
        /// \param pOffset 返回漫反射纹理的偏移量，不关心就传入 nullptr
        /// \param pRotation 返回漫反射纹理的旋转量（单位：角度），不关心就传入 nullptr
        /// \param pScale 返回漫反射纹理的缩放量，不关心就传入 nullptr
        /// \return true-获取成功，false-获取失败
        virtual bool GetOverriddenDiffuseTexureTransformation(Vector2d* pOffset, double* pRotation, Vector2d* pScale) const = 0;

        /// \brief 获取节点的各种属性标识位集合
        /// \return 属性标识位集合
        virtual int GetFlags() const = 0;

        /// \brief 设置节点的属性标识
        /// \param flag 属性标识,第1位：可选择，第2位：可捕捉，第3位：可剖切，第4位：可裁剪，第5位：不导出，
        /// 第6、7位：根据视图剖切面判断或者用户自定义设置，节点位于前景还是背景，如果都没有设置，继承父节点属性。
        /// 第6位：设置节点位于前景；第7位，设置节点位于背景。当 Element 整体为前景或者背景时（ElementForegroundOrBackgroundInfo::Foreground|Background），这两个字段无效。
        ///第8位：设置节点是否参与退让
        ///第9位：设置节点是否显示隐藏线
        /// \return 无
        virtual void SetFlags(int flag) = 0;

        /// \brief 获取节点是否可以被选择
        /// \return true-可以被选择；false-不可以被选择
        virtual bool IsSelectable() const = 0;

        /// \brief 设置节点是否可以被选择
        /// \param selectable true-可以被选择；false-不可以被选择
        /// \return 无
        virtual void SetIsSelectable(bool selectable) = 0;

        /// \brief 获取节点是否可以被捕捉
        /// \return true-可以被捕捉；false-不可以被捕捉
        virtual bool IsSnappable() const = 0;

        /// \brief 设置节点是否可以被捕捉
        /// \param selectable true-可以被捕捉；false-不可以被捕捉
        /// \return true-设置成功；false-设置失败
        virtual bool SetIsSnappable(bool snapable) = 0;

        /// \brief 获取节点是否为剖切节点
        /// \return true-是剖切节点;false-不是剖切节点
        virtual bool IsSectioning() const = 0;

        /// \brief 获取节点可见性
        /// \return 节点可见性。详细请参见枚举GraphicsNodeVisibility类型取值范围
        /// \see GraphicsNodeVisibility
        virtual GraphicsNodeVisibility GetVisibility() const = 0;

        /// \brief 设置节点可见性
        /// \param visibility 参见枚举GraphicsNodeVisibility类型取值范围
        /// \return 无
        virtual void SetVisibility(const GraphicsNodeVisibility& visibility) = 0;

        /// \brief 获取节点是否可被裁剪
        ///
        /// 显示层的裁剪，利用图形API的裁剪面功能，数据层不会被裁剪   
        /// \return true-可以被裁剪；false-不可以被裁剪
        virtual bool IsClippable() const = 0;

        /// \brief 设置节点是否可被裁剪
        /// \param enable true-可以被裁剪；false-不可以被裁剪
        /// \return 无
        virtual void SetIsClippable(bool enable) = 0;

        /// \brief 获取节点是否可被克隆  
        /// \return true-可以被克隆；false-不可以被克隆
        virtual bool IsCloneable() const = 0;

        /// \brief 对节点进行克隆  
        /// \return 返回的克隆节点
        virtual OwnerPtr<IGraphicsNode> Clone() const = 0;

        /// \brief 对节点进行几何变换
        /// \param transMatrix 几何变换矩阵
        /// \return true-成功；false-失败
        virtual bool Transform(const Matrix4d& transMatrix) = 0;

        /// \brief 设置节点的可见性过滤器
        /// \param opFilter 可见性过滤器
        /// \return 无
        virtual void SetVisibilityFilter(OwnerPtr<IGraphicsNodeVisibilityFilter> opFilter) = 0;

        /// \brief 获取节点的可见性过滤器
        /// \return 指向节点的可见性过滤器的指针
        virtual const IGraphicsNodeVisibilityFilter* GetVisibilityFilter() const = 0;

        /// \brief 获取节点引用到的Element对象的id集合
        /// \param ids 节点引用到的Element对象的id集合
        /// \return 无
        virtual void GetReferencedElementIds(std::vector<ElementId>& ids) const = 0;
        virtual void Report(std::set<ElementId>& toKeep) const = 0;

        /// \brief 删除传入的Element对象的id集合
        /// 目前仅在ElementUtils::UpdateForWeakParentDeletion中使用
        /// \param ids 传入的Element对象的id集合
        /// \return 无
        virtual void DeleteReferencedElementIds(const std::vector<ElementId>& ids) = 0;
        
        /// \brief 获取节点是否位于前景
        virtual bool IsInTheForeground() const = 0;

        /// \brief 设置节点是否位于前景。当 Element 整体为前景或者背景时（ElementForegroundOrBackgroundInfo::Foreground|Background），设置无效。
        /// \param isForeground 节点位于前景
        virtual void SetIsInTheForeground(bool isForeground) = 0;

        /// \brief 获取节点是否位于背景景
        virtual bool IsInTheBackground() const = 0;

        /// \brief 设置节点是否位于背景。当 Element 整体为前景或者背景时（ElementForegroundOrBackgroundInfo::Foreground|Background），设置无效。
        /// \param isBackground 节点位于背景
        virtual void SetIsInTheBackground(bool isBackground) = 0;

        /// \brief 获取节点是否参与退让
        virtual bool IsHaloedGapEnabled() const = 0;

        ///\brief 设置节点是否参与退让。
        ///
        ///enable默认值为true, 表示参与退让。 .
        ///此接口的典型应用场景是，排除某些节点不参与退让。
        ///注意，如果当前构建不参与退让，或者当前视图没有开启退让， 此函数即便设置为true也不会有退让效果。
        ///\param enable 为true表示参与退让 
        virtual void SetHaloedGapEnabled(bool enable) = 0;

        /// \brief 获取节点是否显示隐藏线
        virtual bool IsHiddenLineEnabled() const = 0;

        ///\brief 设置节点是否显示隐藏线。
        ///
        ///enable默认值为true, 表示显示隐藏线。
        ///此接口的典型应用场景是，排除某些节点不产生隐藏线。
        ///注意，如果当前构建不显示隐藏线，或者当前视图没开启隐藏线， 此函数即便设置为true也不用有隐藏线创建。
        ///\param enable 为true表示显示隐藏线。 
        virtual void SetHiddenLineEnabled(bool enable) = 0;

        /// \brief 获取渲染层次类型
        /// \return 渲染层次类型，参见：GraphicsRenderLayer
        /// \see GraphicsRenderLayer
        virtual GraphicsRenderLayer GetRenderLayer() const = 0;

        /// \brief 设置渲染层次类型
        /// \param renderLayer 渲染层次类型，参见：GraphicsRenderLayer
        /// \return 无
        /// \see GraphicsRenderLayer
        virtual void SetRenderLayer(GraphicsRenderLayer renderLayer) = 0;

        /// \brief 将图形节点转化为Json对象
        ///
        /// Json格式示例:
        /// {
        /// "graphicsNodeType": 14, //Int32类型，图形节点的类型。比如是Face，Body，Text
        /// "graphicsNodeId" : 1,   //Int32类型
        /// "gStyleId" : 2,         //Int64类型，GStyleElement的ElementId
        /// "geometry" : "xxxxxx",  //GGP二进制几何数据
        /// "subNodes" : [{}, {}]    //数组类型。其中每一个对象也是该Json对象
        /// "vis" :                 //Int32类型，图形节点的可见性，见GraphicsNodeVisibility。
        /// }
        /// \return Json对象
        GCMP_OBSOLETE_API(2021/08/01, IGraphicsNode::ToJson((const IElement* pElement)) const)virtual Json::Value ToJson() const = 0;
    };
}

